package linuxbox.poll.logic;

import java.util.*;
import java.sql.*;
//import java.text.*;

import linuxbox.BoxStatic;
import linuxbox.exception.*;
import linuxbox.util.*;
import linuxbox.bean.*;

import linuxbox.poll.bean.*;

public class BoxPoll
{
  public final static String VT_ALL = "ALL";
  public final static String VT_OPEN = "OPEN";
  public final static String VT_CLOSED = "CLOSED";

  public BoxPoll()
  {
  }

  public BoxPollEntry get(BaseIntKey key)
  {
    BoxPollEntry entry = null;
    try
    {
      BoxPollEntryBean bean = new BoxPollEntryBean(key);
      bean.load();
      entry = new BoxPollEntry();
      entry.copyFrom(bean);
    }
    catch (Exception e)
    {
      //TODO: Log something?
      e.printStackTrace();
    }
    return entry;
  }

  public BoxPollEntry add()
  {
    try
    {
      BoxPollEntryBean bean = new BoxPollEntryBean(new BaseIntKey(0));
      bean.create();

      BoxPollEntry entry = new BoxPollEntry();
      entry.copyFrom(bean);
      return entry;
    }
    catch (Exception e)
    {
      //TODO: Log something?
      e.printStackTrace();
    }
    return null;
  }

  public boolean remove(BaseIntKey key)
  {
    try
    {
      DbAdapter db = new DbAdapter(true);
      BoxPollEntryBean bean = new BoxPollEntryBean(key,db);
      bean.remove();
      //Also remove all choices and replies
      BoxPollChoiceEntryBean choiceBean = new BoxPollChoiceEntryBean(null,db);
      String sql = "DELETE FROM " + choiceBean.getTableName() + " where pollid=" + key.getID();
      choiceBean.updateBySql(sql);

      BoxPollReplyEntryBean replyBean = new BoxPollReplyEntryBean(null,db);
      sql = "DELETE FROM " + replyBean.getTableName() + " where pollid=" + key.getID();
      replyBean.updateBySql(sql);

      db.close();
      db = null;
    }
    catch (Exception e)
    {
      //TODO: Log something?
      e.printStackTrace();
      return false;
    }
    return true;
  }

  public boolean update(BoxPollEntry entry)
  {
    try
    {
      BoxPollEntryBean bean = new BoxPollEntryBean(new BaseIntKey(entry.getID()));
      bean.copyFrom(entry);
      bean.store();
    }
    catch (Exception e)
    {
      //TODO: Log something?
      e.printStackTrace();
      return false;
    }
    return true;
  }

  /**
    get the choices I voted
    ??? Why the Iterator doesn't have reset(), if I want to use the
    Iterator more than once, I have to return the Vector
  */
  public Vector getMyVotes(int pollID, int userID)
  {
    if ( pollID == 0 || userID == -1)
      return null;

    Vector v = new Vector();
    try
    {
      // Use the transaction, pass the DbAdapter to the bean
      DbAdapter db = new DbAdapter(true);
      BoxPollReplyEntryBean bean = new BoxPollReplyEntryBean(null,db);
      String sql = " where pollid=" + pollID + " and userid=" + userID;
      Iterator it = bean.findBySql(sql);
      while (it.hasNext())
      {
        BaseIntKey key = (BaseIntKey) it.next();
        bean = new BoxPollReplyEntryBean(key,db);
        bean.load();
        BoxPollReplyEntry entry = new BoxPollReplyEntry();
        entry.copyFrom(bean);
        v.add(entry);
      }
      db.close();
      db = null;
    }
    catch (Exception e)
    {
      e.printStackTrace();
    //TODO: Log
    }
    return v;
  }

  /**
    get the choices of a poll
  */
  public Iterator getChoices(int id)
  {
    if ( id == 0 )
      return null;
    Vector v = new Vector();
    try
    {
      // Use the transaction, pass the DbAdapter to the bean
      DbAdapter db = new DbAdapter(true);
      BoxPollChoiceEntryBean bean = new BoxPollChoiceEntryBean(null,db);
      String sql = " where pollid = " + id;
      Iterator it = bean.findBySql(sql);
      while (it.hasNext())
      {
        BaseIntKey key = (BaseIntKey) it.next();
        bean = new BoxPollChoiceEntryBean(key,db);
        bean.load();
        BoxPollChoiceEntry entry = new BoxPollChoiceEntry();
        entry.copyFrom(bean);
        v.add(entry);
      }
      db.close();
      db = null;
    }
    catch (Exception e)
    {
      e.printStackTrace();
    //TODO: Log
    }
    return v.iterator();
  }

  public int getTotalReplies(int pollID)
  {
    BoxPollReplyEntryBean bean = new BoxPollReplyEntryBean(null);
    String sql = "select count(id) from "+bean.getTableName()
                  +" where pollID="+pollID;
    try
    {
      return bean.getCount(sql);
    }
    catch(Exception e)
    {
      return 0;
    }
  }

  public int getCountForChoice(int choiceID)
  {
    BoxPollReplyEntryBean bean = new BoxPollReplyEntryBean(null);
    String sql = "select count(id) from "+bean.getTableName()
                  +" where choiceid="+choiceID;
    try
    {
      return bean.getCount(sql);
    }
    catch(Exception e)
    {
      return 0;
    }
  }

  public Iterator getRepliesForChoice(int choiceID)
  {
    if ( choiceID == 0 )
      return null;
    Vector v = new Vector();
    try
    {
      // Use the transaction, pass the DbAdapter to the bean
      DbAdapter db = new DbAdapter(true);
      BoxPollReplyEntryBean bean = new BoxPollReplyEntryBean(null,db);
      String sql = " where choiceid = " + choiceID;
      Iterator it = bean.findBySql(sql);
      while (it.hasNext())
      {
        BaseIntKey key = (BaseIntKey) it.next();
        bean = new BoxPollReplyEntryBean(key,db);
        bean.load();
        BoxPollReplyEntry entry = new BoxPollReplyEntry();
        entry.copyFrom(bean);
        v.add(entry);
      }
      db.close();
      db = null;
    }
    catch (Exception e)
    {
      e.printStackTrace();
    //TODO: Log
    }
    return v.iterator();
  }

  public boolean doConclude(int pollID, int sendresult)
  {
    try
    {
      BoxPollEntryBean bean = new BoxPollEntryBean(new BaseIntKey(pollID));
      bean.load();
      bean.setClosed(true);
      bean.setConcludeTime(new Timestamp(new java.util.Date().getTime()));
      bean.store();

      //sendresult == 0, means use the default one in the bean
      if (sendresult == 0)
        sendresult = bean.getSendResult();
    }
    catch (Exception e)
    {
      //TODO: Log something?
      e.printStackTrace();
      return false;
    }

    if ( sendresult == 1 )
    {
      System.out.println("//TODO: send result to all voters through email");
    }
    else if ( sendresult == 2 )
    {
      System.out.println("//TODO: send result to the poll author through email");
    }
    return true;
  }

  public boolean doAutoConclude()
  {
    try
    {
      BoxStatic.dateTimeFormatter.applyPattern(BoxStatic.POSTGRES_DATE_FORMAT);
      Calendar today= Calendar.getInstance();

      StringBuffer sql = new StringBuffer();
      sql.append(" where closed=0 and manualconclude=0 and concludetime<'");
      String strDate = BoxStatic.dateTimeFormatter.format(today.getTime());
      sql.append(strDate);
      sql.append("'");

      BoxPollEntryBean bean = new BoxPollEntryBean(null);
      Iterator it = bean.findBySql(sql.toString());
      if (it != null && it.hasNext())
      {
        BaseIntKey key = (BaseIntKey) it.next();
        if (key != null)
        {
          doConclude(key.getID(), 0);
        }
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return false;
    }
    return true;
  }

  public boolean updateVotes(int userID, int pollID, String[] replies)
  {
    if ( pollID == 0 || userID == -1 )
      return false;
    //Remove all the old votes, and add the new votes
    try
    {
      // Use the transaction, pass the DbAdapter to the bean
      DbAdapter db = new DbAdapter(true);
      //clear the replies
      BoxPollReplyEntryBean replyBean = new BoxPollReplyEntryBean(null,db);
      String sql = "DELETE FROM " + replyBean.getTableName() + " where pollid=" + pollID
                   + " and userid="+userID;
      replyBean.updateBySql(sql);
      if ( replies != null )
      {
        for(int i=0; i < replies.length; i++)
        {
          replyBean = new BoxPollReplyEntryBean(new BaseIntKey(0),db);
          replyBean.create();
          replyBean.setPollID(pollID);
          replyBean.setUserID(userID);
          replyBean.setChoiceID(Integer.parseInt(replies[i]));
          replyBean.store();
        }
      }
      db.close();
      db = null;
    }
    catch(Exception e)
    {
      e.printStackTrace();
    //TODO: Log
      return false;
    }

    return true;
  }

  public boolean updateChoices(int id, String[] choices)
  {
    if ( id == 0 )
      return false;
    //Remove all the old choices, and add the new choices
    try
    {
      // Use the transaction, pass the DbAdapter to the bean
      DbAdapter db = new DbAdapter(true);
      //clear the choices
      BoxPollChoiceEntryBean choiceBean = new BoxPollChoiceEntryBean(null,db);
      String sql = "DELETE FROM " + choiceBean.getTableName() + " where pollid=" + id;
      choiceBean.updateBySql(sql);

      //clear the replies
      BoxPollReplyEntryBean replyBean = new BoxPollReplyEntryBean(null,db);
      sql = "DELETE FROM " + replyBean.getTableName() + " where pollid=" + id;
      replyBean.updateBySql(sql);

      if ( choices != null )
      {
        for(int i=0; i < choices.length; i++)
        {
          choiceBean = new BoxPollChoiceEntryBean(new BaseIntKey(0),db);
          choiceBean.create();
          choiceBean.setPollID(id);
          choiceBean.setChoice(choices[i]);
          choiceBean.store();
        }
      }
      db.close();
      db = null;
    }
    catch(Exception e)
    {
      e.printStackTrace();
    //TODO: Log
      return false;
    }

    return true;
  }


  public int getTotalPages(int entriesPerPage, String VIEW_TYPE)
  {
    int pages = 1;
    try
    {
      String sql = null;
      if (VIEW_TYPE.compareTo(VT_OPEN) == 0)
      {
        sql = " where closed=0 ";
      }
      else if (VIEW_TYPE.compareTo(VT_CLOSED) == 0)
      {
        sql = " where closed=1 ";
      }
      else
      {
        sql = "";
      }

      BoxPollEntryBean bean = new BoxPollEntryBean(null,null);
      pages = ((bean.getCountBySql(sql.toString()) - 1) / entriesPerPage) + 1;
    }
    catch (Exception e)
    {
      e.printStackTrace();
    //TODO: Log
    }
    return pages;
  }

  public Iterator getPolls(String VIEW_TYPE, String SORTBY, boolean sortAsc, int from, int limit)
  {
    if ( VT_OPEN.compareTo(VIEW_TYPE) == 0)
    {
      return getOpenPolls(SORTBY, sortAsc, from, limit);
    }
    else if ( VT_CLOSED.compareTo(VIEW_TYPE) == 0)
    {
      return getClosedPolls(SORTBY, sortAsc, from, limit);
    }
    else
    {
      return getAllPolls(SORTBY, sortAsc, from, limit);
    }
  }

  public Iterator getAllPolls(String SORTBY, boolean sortAsc, int from, int limit)
  {
    StringBuffer sql = new StringBuffer();
    sql.append(" order by ");
    sql.append(SORTBY);
    if (sortAsc)
      sql.append(" ASC ");
    else
      sql.append(" DESC ");

    DBUtil.appendLimit(sql, from, limit);
    return getBySql(sql.toString());
  }

  /**
    get polls that are still open
  */
  public Iterator getOpenPolls(String SORTBY, boolean sortAsc, int from, int limit)
  {
    StringBuffer sql = new StringBuffer();
    sql.append(" where closed=0 ");
    sql.append(" order by ");
    sql.append(SORTBY);
    if (sortAsc)
      sql.append(" ASC ");
    else
      sql.append(" DESC ");

    DBUtil.appendLimit(sql, from, limit);
    return getBySql(sql.toString());
  }

  /**
    get closed polls
  */
  public Iterator getClosedPolls(String SORTBY, boolean sortAsc, int from, int limit)
  {
    StringBuffer sql = new StringBuffer();
    sql.append(" where closed=1 ");
    sql.append(" order by ");
    sql.append(SORTBY);
    if (sortAsc)
      sql.append(" ASC ");
    else
      sql.append(" DESC ");

    DBUtil.appendLimit(sql, from, limit);
    return getBySql(sql.toString());
  }

  protected Iterator getBySql(String sql)
  {
    Vector v = new Vector();
    try
    {
      // Use the transaction, pass the DbAdapter to the bean
      DbAdapter db = new DbAdapter(true);
      BoxPollEntryBean bean = new BoxPollEntryBean(null,db);
      Iterator it = bean.findBySql(sql);
      while (it.hasNext())
      {
        BaseIntKey key = (BaseIntKey) it.next();
        bean = new BoxPollEntryBean(key,db);
        bean.load();
        BoxPollEntry entry = new BoxPollEntry();
        entry.copyFrom(bean);
        v.add(entry);
      }
      db.close();
      db = null;
    }
    catch (Exception e)
    {
      e.printStackTrace();
    //TODO: Log
    }
    return v.iterator();
  }
}
